1 using System.Collections.Generic;
2 using
UnityEngine;
3
4 namespace
ProceduralToolkit.Examples
5 {
6     
public abstract class ProceduralFacadePanel : IFacadePanel
7     {
8         
public Vector2? origin { get; set; }
9         
public float? width { get; set; }
10         
public float? height { get; set; }
11
12         
private const float SocleWindowWidth = 0.7f;
13         
private const float SocleWindowHeight = 0.4f;
14         
private const float SocleWindowDepth = 0.1f;
15         
private const float SocleWindowHeightOffset = 0.1f;
16
17         
private const float EntranceDoorWidth = 1.8f;
18         
private const float EntranceDoorHeight = 2;
19         
private const float EntranceDoorThickness = 0.05f;
20
21         
private const float EntranceRoofLength = 1;
22         
private const float EntranceRoofHeight = 0.15f;
23
24         
private const float EntranceWindowWidthOffset = 0.4f;
25         
private const float EntranceWindowHeightOffset = 0.3f;
26
27         
private const float WindowDepth = 0.1f;
28         
private const float WindowWidthOffset = 0.5f;
29         
private const float WindowBottomOffset = 1;
30         
private const float WindowTopOffset = 0.3f;
31         
private const float WindowFrameWidth = 0.05f;
32         
private const float WindowSegmentMinWidth = 0.9f;
33
34         
private const float BalconyHeight = 1;
35         
private const float BalconyDepth = 0.8f;
36         
private const float BalconyThickness = 0.1f;
37
38         
private const float AtticHoleWidth = 0.3f;
39         
private const float AtticHoleHeight = 0.3f;
40         
private const float AtticHoleDepth = 0.5f;
41
42         
public abstract MeshDraft GetMeshDraft();
43
44         
protected static MeshDraft PerforatedQuad(
45             Vector3 min,
46             Vector3 max,
47             Vector3 innerMin,
48             Vector3 innerMax)
49         {
50             Vector3 size = max - min;
51             Vector3 widthVector = size.OnlyXZ();
52             Vector3 heightVector = size.OnlyY();
53             Vector3 normal = Vector3.Cross(heightVector, widthVector).normalized;
54
55             Vector3 innerSize = innerMax - innerMin;
56             Vector3 innerHeight = innerSize.OnlyY();
57             Vector3 innerWidth = innerSize.OnlyXZ();
58
59             Vector3 vertex0 = min;
60             Vector3 vertex1 = min + heightVector;
61             Vector3 vertex2 = max;
62             Vector3 vertex3 = min + widthVector;
63             Vector3 window0 = innerMin;
64             Vector3 window1 = innerMin + innerHeight;
65             Vector3 window2 = innerMax;
66             Vector3 window3 = innerMin + innerWidth;
67
68             
return new MeshDraft
69             {
70                 vertices =
new List<Vector3>(8)
71                 {
72                     vertex0,
73                     vertex1,
74                     vertex2,
75                     vertex3,
76                     window0,
77                     window1,
78                     window2,
79                     window3,
80                 },
81                 normals =
new List<Vector3>(8) {normal, normal, normal, normal, normal, normal, normal, normal},
82                 triangles =
new List<int>(24) {0, 1, 4, 4, 1, 5, 1, 2, 5, 5, 2, 6, 2, 3, 6, 6, 3, 7, 3, 0, 7, 7, 0, 4,}
83             };
84         }
85
86         
public static MeshDraft Window(
87             Vector3 origin,
88             
float width,
89             
float height,
90             Color wallColor,
91             Color frameColor,
92             Color glassColor)
93         {
94             
return Window(origin, width, height, WindowWidthOffset, WindowBottomOffset, WindowTopOffset, wallColor,
95                 frameColor, glassColor);
96         }
97
98         
protected static MeshDraft Window(
99             Vector3 min,
100             
float width,
101             
float height,
102             
float widthOffset,
103             
float bottomOffset,
104             
float topOffset,
105             Color wallColor,
106             Color frameColor,
107             Color glassColor)
108         {
109             Vector3 widthVector = Vector3.right*width;
110             Vector3 heightVector = Vector3.up*height;
111             Vector3 max = min + widthVector + heightVector;
112             Vector3 frameMin = min + Vector3.right*widthOffset + Vector3.up*bottomOffset;
113             Vector3 frameMax = max - Vector3.right*widthOffset - Vector3.up*topOffset;
114             Vector3 frameWidth = Vector3.right*(width - widthOffset*
2);
115             Vector3 frameHeight = Vector3.up*(height - bottomOffset - topOffset);
116             Vector3 frameDepth = Vector3.forward*WindowDepth;
117             Vector3 frameSize = frameMax - frameMin;
118
119             
var draft = PerforatedQuad(min, max, frameMin, frameMax);
120
121             
var frame = MeshDraft.PartialBox(frameWidth, -frameDepth, frameHeight,
122                 Directions.All & ~Directions.ZAxis);
123             frame.Move(frameMin + frameSize/
2 + frameDepth/2);
124             draft.Add(frame);
125             draft.Paint(wallColor);
126
127             draft.Add(Windowpane(frameMin + frameDepth, frameMax + frameDepth, frameColor, glassColor));
128
129             
return draft;
130         }
131
132         
private static MeshDraft Windowpane(Vector3 min, Vector3 max, Color frameColor, Color glassColor)
133         {
134             Vector3 size = max - min;
135             Vector3 widthVector = size.OnlyXZ();
136             Vector3 heightVector = size.OnlyY();
137             Vector3 right = widthVector.normalized;
138             Vector3 normal = Vector3.Cross(widthVector, heightVector).normalized;
139             
var draft = new MeshDraft();
140
141             
int rodCount = Mathf.FloorToInt(widthVector.magnitude/WindowSegmentMinWidth);
142             
float interval = widthVector.magnitude/(rodCount + 1);
143
144             Vector3 frameWidth = right*WindowFrameWidth/
2;
145             Vector3 frameHeight = Vector3.up*WindowFrameWidth/
2;
146             Vector3 frameLength = normal*WindowFrameWidth/
2;
147             Vector3 startPosition = min + heightVector/
2 + frameLength/2;
148             
for (int i = 0; i < rodCount; i++)
149             {
150                 
var frame = MeshDraft.PartialBox(frameWidth*2, frameLength, heightVector - frameHeight*2,
151                     Directions.Left | Directions.Back | Directions.Right);
152                 frame.Move(startPosition + right*(i +
1)*interval);
153                 draft.Add(frame);
154             }
155
156             Vector3 windowMin = min + frameWidth + frameHeight;
157             Vector3 windowWidth = widthVector - frameWidth*
2;
158             Vector3 windowHeight = heightVector - frameHeight*
2;
159             Vector3 windowMax = windowMin + windowWidth + windowHeight;
160             
var window = PerforatedQuad(min, max, windowMin, windowMax);
161             draft.Add(window);
162
163             
var hole = MeshDraft.PartialBox(windowWidth, frameLength, windowHeight, Directions.All & ~Directions.ZAxis);
164             hole.Move(startPosition + widthVector/
2);
165             hole.FlipFaces();
166             draft.Add(hole);
167             draft.Paint(frameColor);
168
169             
var glass = MeshDraft.Quad(windowMin + frameLength, windowWidth, windowHeight);
170             glass.Paint(glassColor);
171             draft.Add(glass);
172
173             
return draft;
174         }
175
176         
protected static MeshDraft Balcony(
177             Vector3 origin,
178             
float width,
179             
float height,
180             Color wallColor,
181             Color frameColor,
182             Color glassColor)
183         {
184             Vector3 widthVector = Vector3.right*width;
185             Vector3 heightVector = Vector3.up*height;
186
187             
var draft = Balcony(origin, width, wallColor);
188
189             Vector3 innerHeightOffset = Vector3.up*BalconyThickness;
190
191             Vector3 windowHeightOffset = Vector3.up*WindowBottomOffset;
192             Vector3 windowWidth = Vector3.right*(width - WindowWidthOffset*
2);
193             Vector3 windowHeight = Vector3.up*(height - WindowBottomOffset - WindowTopOffset);
194             Vector3 windowDepth = Vector3.forward*WindowDepth;
195
196             
int rodCount = Mathf.FloorToInt(windowWidth.magnitude/WindowSegmentMinWidth);
197             Vector3 doorWidth = Vector3.right*windowWidth.magnitude/(rodCount +
1);
198             Vector3 doorHeight = windowHeightOffset + windowHeight;
199
200             Vector3 outerFrameOrigin = origin + Vector3.right*WindowWidthOffset;
201             List<Vector3> outerFrame =
new List<Vector3>
202             {
203                 outerFrameOrigin + innerHeightOffset,
204                 outerFrameOrigin + doorHeight,
205                 outerFrameOrigin + windowWidth + doorHeight,
206                 outerFrameOrigin + windowWidth + windowHeightOffset,
207                 outerFrameOrigin + doorWidth + windowHeightOffset,
208                 outerFrameOrigin + doorWidth + innerHeightOffset
209             };
210
211             
var panel = MeshDraft.TriangleStrip(new List<Vector3>
212             {
213                 outerFrame[
0],
214                 origin,
215                 outerFrame[
1],
216                 origin + heightVector,
217                 outerFrame[
2],
218                 origin + widthVector + heightVector,
219                 outerFrame[
3],
220                 origin + widthVector,
221                 outerFrame[
4],
222                 origin + widthVector,
223                 outerFrame[
5]
224             });
225             panel.Paint(wallColor);
226
227             draft.Add(panel);
228
229             List<Vector3> innerFrame =
new List<Vector3>();
230             
foreach (Vector3 vertex in outerFrame)
231             {
232                 innerFrame.Add(vertex - windowDepth);
233             }
234             
var frame = MeshDraft.FlatBand(innerFrame, outerFrame);
235             frame.Paint(wallColor);
236             draft.Add(frame);
237
238             Vector3 windowpaneMin1 = outerFrame[
0] - windowDepth;
239             Vector3 windowpaneMin2 = outerFrame[
4] - windowDepth;
240             draft.Add(Windowpane(windowpaneMin1, windowpaneMin1 + doorWidth + doorHeight - innerHeightOffset,
241                 frameColor, glassColor));
242             draft.Add(Windowpane(windowpaneMin2, windowpaneMin2 + windowWidth - doorWidth + windowHeight,
243                 frameColor, glassColor));
244
245             
return draft;
246         }
247
248         
private static MeshDraft Balcony(Vector3 origin, float width, Color wallColor)
249         {
250             Vector3 widthVector = Vector3.right*width;
251             Vector3 balconyHeight = Vector3.up*BalconyHeight;
252             Vector3 balconyDepth = Vector3.back*BalconyDepth;
253
254             
var balconyOuter = MeshDraft.PartialBox(widthVector, balconyDepth, balconyHeight,
255                 Directions.All & ~Directions.Up & ~Directions.Back);
256             balconyOuter.FlipFaces();
257             Vector3 balconyCenter = origin + widthVector/
2 + balconyDepth/2 + balconyHeight/2;
258             balconyOuter.Move(balconyCenter);
259
260             Vector3 innerWidthOffset = Vector3.right*BalconyThickness;
261             Vector3 innerWidth = widthVector - innerWidthOffset*
2;
262             Vector3 innerHeightOffset = Vector3.up*BalconyThickness;
263             Vector3 innerHeight = balconyHeight - innerHeightOffset;
264             Vector3 innerDepthOffset = Vector3.back*BalconyThickness;
265             Vector3 innerDepth = balconyDepth - innerDepthOffset;
266             
var balconyInner = MeshDraft.PartialBox(innerWidth, innerDepth, innerHeight,
267                 Directions.All & ~Directions.Up & ~Directions.Back);
268             balconyInner.Move(balconyCenter - innerDepthOffset/
2 + innerHeightOffset/2);
269
270             Vector3 borderOrigin = origin + widthVector + balconyHeight;
271             Vector3 borderInnerOrigin = borderOrigin - innerWidthOffset;
272             
var balconyBorder = Bracket(borderOrigin, -widthVector, balconyDepth,
273                 borderInnerOrigin, -innerWidth, innerDepth);
274
275             
var balcony = new MeshDraft();
276             balcony.Add(balconyOuter);
277             balcony.Add(balconyInner);
278             balcony.Add(balconyBorder);
279             balcony.Paint(wallColor);
280             
return balcony;
281         }
282
283         
private static MeshDraft Bracket(Vector3 origin, Vector3 width, Vector3 length,
284             Vector3 innerOrigin, Vector3 innerWidth, Vector3 innerLength)
285         {
286             
return MeshDraft.TriangleStrip(new List<Vector3>
287             {
288                 innerOrigin,
289                 origin,
290                 innerOrigin + innerLength,
291                 origin + length,
292                 innerOrigin + innerLength + innerWidth,
293                 origin + length + width,
294                 innerOrigin + innerWidth,
295                 origin + width
296             });
297         }
298
299         
protected static MeshDraft BalconyGlazed(Vector3 origin, float width, float height, Color wallColor,
300             Color frameColor, Color glassColor, Color roofColor)
301         {
302             Vector3 widthVector = Vector3.right*width;
303             Vector3 heightVector = Vector3.up*height;
304
305             Vector3 balconyHeight = Vector3.up*BalconyHeight;
306             Vector3 balconyDepth = Vector3.back*BalconyDepth;
307
308             
var draft = new MeshDraft();
309             
var balcony = MeshDraft.PartialBox(widthVector, balconyDepth, balconyHeight,
310                 Directions.All & ~Directions.Up & ~Directions.Back);
311             balcony.FlipFaces();
312             balcony.Move(origin + widthVector/
2 + balconyDepth/2 + balconyHeight/2);
313             balcony.Paint(wallColor);
314             draft.Add(balcony);
315
316             Vector3 roof0 = origin + heightVector;
317             Vector3 roof1 = roof0 + widthVector;
318             Vector3 roof2 = roof1 + balconyDepth;
319             Vector3 roof3 = roof0 + balconyDepth;
320             
var roof = MeshDraft.Quad(roof0, roof1, roof2, roof3);
321             roof.Paint(roofColor);
322             draft.Add(roof);
323
324             Vector3 glassHeight = heightVector - balconyHeight;
325             Vector3 glass0 = origin + balconyHeight;
326             Vector3 glass1 = glass0 + balconyDepth;
327             Vector3 glass2 = glass1 + widthVector;
328             
var glass = Windowpane(glass0, glass0 + balconyDepth + glassHeight, frameColor, glassColor);
329             glass.Add(Windowpane(glass1, glass1 + widthVector + glassHeight, frameColor, glassColor));
330             glass.Add(Windowpane(glass2, glass2 - balconyDepth + glassHeight, frameColor, glassColor));
331             draft.Add(glass);
332
333             
return draft;
334         }
335
336         
protected static MeshDraft Entrance(Vector3 origin, float width, float height, Color wallColor, Color doorColor)
337         {
338             Vector3 widthVector = Vector3.right*width;
339             Vector3 heightVector = Vector3.up*height;
340
341             Vector3 doorWidth = Vector3.right*EntranceDoorWidth;
342             Vector3 doorHeight = Vector3.up*EntranceDoorHeight;
343             Vector3 doorThickness = Vector3.back*EntranceDoorThickness;
344             Vector3 doorOrigin = origin + widthVector/
2 - doorWidth/2;
345
346             
var draft = Bracket(origin, widthVector, heightVector, doorOrigin, doorWidth, doorHeight);
347             draft.Paint(wallColor);
348
349             
var doorFrame = MeshDraft.PartialBox(doorWidth, -doorThickness, doorHeight,
350                 Directions.All & ~Directions.ZAxis);
351             doorFrame.Move(doorOrigin + doorWidth/
2 + doorHeight/2 + doorThickness/2);
352             doorFrame.Paint(doorColor);
353             draft.Add(doorFrame);
354
355             
var door = MeshDraft.Quad(doorOrigin + doorThickness, doorWidth, doorHeight);
356             door.Paint(doorColor);
357             draft.Add(door);
358             
return draft;
359         }
360
361         
protected static MeshDraft EntranceRoofed(Vector3 origin, float width, float height, Color wallColor,
362             Color doorColor, Color roofColor)
363         {
364             
var draft = Entrance(origin, width, height, wallColor, doorColor);
365             Vector3 widthVector = Vector3.right*width;
366             Vector3 lengthVector = Vector3.forward*EntranceRoofLength;
367
368             
var roof = MeshDraft.PartialBox(widthVector, lengthVector, Vector3.up*EntranceRoofHeight,
369                 Directions.All & ~Directions.Forward);
370             roof.Move(origin + widthVector/
2 + Vector3.up*(height - EntranceRoofHeight/2) - lengthVector/2);
371             roof.Paint(roofColor);
372             draft.Add(roof);
373             
return draft;
374         }
375
376         
protected static MeshDraft EntranceWindow(Vector3 origin, float width, float height, Color wallColor,
377             Color frameColor, Color glassColor)
378         {
379             
var draft = Window(origin, width, height/2, EntranceWindowWidthOffset, EntranceWindowHeightOffset,
380                 EntranceWindowHeightOffset, wallColor, frameColor, glassColor);
381             draft.Add(Window(origin + Vector3.up*height/
2, width, height/2, EntranceWindowWidthOffset,
382                 EntranceWindowHeightOffset, EntranceWindowHeightOffset, wallColor, frameColor, glassColor));
383             
return draft;
384         }
385
386         
protected static MeshDraft SocleWindowed(Vector3 origin, float width, float height, Color wallColor,
387             Color glassColor)
388         {
389             Vector3 widthVector = Vector3.right*width;
390             Vector3 heightVector = Vector3.up*height;
391
392             Vector3 windowWidth = Vector3.right*SocleWindowWidth;
393             Vector3 windowHeigth = Vector3.up*SocleWindowHeight;
394             Vector3 windowDepth = Vector3.forward*SocleWindowDepth;
395             Vector3 windowOrigin = origin + widthVector/
2 - windowWidth/2 + Vector3.up*SocleWindowHeightOffset;
396             Vector3 windowMax = windowOrigin + windowWidth + windowHeigth;
397
398             
var wall = PerforatedQuad(origin, origin + widthVector + heightVector, windowOrigin, windowMax);
399
400             
var frame = MeshDraft.PartialBox(windowWidth, -windowDepth, windowHeigth,
401                 Directions.All & ~Directions.ZAxis);
402             frame.Move(windowOrigin + windowWidth/
2 + windowHeigth/2 + windowDepth/2);
403             wall.Add(frame);
404             wall.Paint(wallColor);
405
406             
var window = MeshDraft.Quad(windowOrigin + windowDepth/2, windowWidth, windowHeigth);
407             window.Paint(glassColor);
408             wall.Add(window);
409
410             
return wall;
411         }
412
413         
protected static MeshDraft AtticVented(Vector3 origin, float width, float height, Color wallColor,
414             Color holeColor)
415         {
416             Vector3 widthVector = Vector3.right*width;
417             Vector3 heightVector = Vector3.up*height;
418             Vector3 center = origin + widthVector/
2 + heightVector/2;
419
420             Vector3 holeOrigin = center - Vector3.right*AtticHoleWidth/
2 - Vector3.up*AtticHoleHeight/2;
421             Vector3 holeWidth = Vector3.right*AtticHoleWidth;
422             Vector3 holeHeight = Vector3.up*AtticHoleHeight;
423             Vector3 holeDepth = Vector3.forward*AtticHoleDepth;
424
425             
var draft = PerforatedQuad(origin, origin + widthVector + heightVector, holeOrigin,
426                 holeOrigin + holeWidth + holeHeight);
427             draft.Paint(wallColor);
428
429             
var hexahedron = MeshDraft.PartialBox(holeWidth, holeDepth, holeHeight, Directions.All & ~Directions.Back);
430             hexahedron.Move(center + holeDepth/
2);
431             hexahedron.FlipFaces();
432             hexahedron.Paint(holeColor);
433             draft.Add(hexahedron);
434             
return draft;
435         }
436     }
437
438     
public class ProceduralWall : ProceduralFacadePanel
439     {
440         
private Color wallColor;
441
442         
public ProceduralWall(Color wallColor)
443         {
444             
this.wallColor = wallColor;
445         }
446
447         
public override MeshDraft GetMeshDraft()
448         {
449             
var draft = MeshDraft.Quad(origin.Value, Vector3.right*width.Value, Vector3.up*height.Value);
450             draft.Paint(wallColor);
451             
return draft;
452         }
453     }
454
455     
public class ProceduralWindow : ProceduralFacadePanel
456     {
457         
private Color wallColor;
458         
private Color frameColor;
459         
private Color glassColor;
460
461         
public ProceduralWindow(Color wallColor, Color frameColor, Color glassColor)
462         {
463             
this.wallColor = wallColor;
464             
this.frameColor = frameColor;
465             
this.glassColor = glassColor;
466         }
467
468         
public override MeshDraft GetMeshDraft()
469         {
470             
return Window(origin.Value, width.Value, height.Value, wallColor, frameColor, glassColor);
471         }
472     }
473
474     
public class ProceduralBalcony : ProceduralFacadePanel
475     {
476         
private Color wallColor;
477         
private Color frameColor;
478         
private Color glassColor;
479
480         
public ProceduralBalcony(Color wallColor, Color frameColor, Color glassColor)
481         {
482             
this.wallColor = wallColor;
483             
this.frameColor = frameColor;
484             
this.glassColor = glassColor;
485         }
486
487         
public override MeshDraft GetMeshDraft()
488         {
489             
return Balcony(origin.Value, width.Value, height.Value, wallColor, frameColor, glassColor);
490         }
491     }
492
493     
public class ProceduralBalconyGlazed : ProceduralFacadePanel
494     {
495         
private Color wallColor;
496         
private Color frameColor;
497         
private Color glassColor;
498         
private Color roofColor;
499
500         
public ProceduralBalconyGlazed(Color wallColor, Color frameColor, Color glassColor, Color roofColor)
501         {
502             
this.wallColor = wallColor;
503             
this.frameColor = frameColor;
504             
this.glassColor = glassColor;
505             
this.roofColor = roofColor;
506         }
507
508         
public override MeshDraft GetMeshDraft()
509         {
510             
return BalconyGlazed(origin.Value, width.Value, height.Value, wallColor, frameColor, glassColor, roofColor);
511         }
512     }
513
514     
public class ProceduralEntrance : ProceduralFacadePanel
515     {
516         
private Color wallColor;
517         
private Color doorColor;
518
519         
public ProceduralEntrance(Color wallColor, Color doorColor)
520         {
521             
this.wallColor = wallColor;
522             
this.doorColor = doorColor;
523         }
524
525         
public override MeshDraft GetMeshDraft()
526         {
527             
return Entrance(origin.Value, width.Value, height.Value, wallColor, doorColor);
528         }
529     }
530
531     
public class ProceduralEntranceRoofed : ProceduralFacadePanel
532     {
533         
private Color wallColor;
534         
private Color doorColor;
535         
private Color roofColor;
536
537         
public ProceduralEntranceRoofed(Color wallColor, Color doorColor, Color roofColor)
538         {
539             
this.wallColor = wallColor;
540             
this.doorColor = doorColor;
541             
this.roofColor = roofColor;
542         }
543
544         
public override MeshDraft GetMeshDraft()
545         {
546             
return EntranceRoofed(origin.Value, width.Value, height.Value, wallColor, doorColor, roofColor);
547         }
548     }
549
550     
public class ProceduralEntranceWindow : ProceduralFacadePanel
551     {
552         
private Color wallColor;
553         
private Color frameColor;
554         
private Color glassColor;
555
556         
public ProceduralEntranceWindow(Color wallColor, Color frameColor, Color glassColor)
557         {
558             
this.wallColor = wallColor;
559             
this.frameColor = frameColor;
560             
this.glassColor = glassColor;
561         }
562
563         
public override MeshDraft GetMeshDraft()
564         {
565             
return EntranceWindow(origin.Value, width.Value, height.Value, wallColor, frameColor, glassColor);
566         }
567     }
568
569     
public class ProceduralSocle : ProceduralWall
570     {
571         
public ProceduralSocle(Color wallColor) : base(wallColor)
572         {
573         }
574     }
575
576     
public class ProceduralSocleWindowed : ProceduralFacadePanel
577     {
578         
private Color wallColor;
579         
private Color glassColor;
580
581         
public ProceduralSocleWindowed(Color wallColor, Color glassColor)
582         {
583             
this.wallColor = wallColor;
584             
this.glassColor = glassColor;
585         }
586
587         
public override MeshDraft GetMeshDraft()
588         {
589             
return SocleWindowed(origin.Value, width.Value, height.Value, wallColor, glassColor);
590         }
591     }
592
593     
public class ProceduralAtticVented : ProceduralFacadePanel
594     {
595         
private Color wallColor;
596         
private Color holeColor;
597
598         
public ProceduralAtticVented(Color wallColor, Color holeColor)
599         {
600             
this.wallColor = wallColor;
601             
this.holeColor = holeColor;
602         }
603
604         
public override MeshDraft GetMeshDraft()
605         {
606             
return AtticVented(origin.Value, width.Value, height.Value, wallColor, holeColor);
607         }
608     }
609 }


Gõ tìm kiếm nhanh...